﻿module StochasticSimulation.SSA.ChemicalReaction.Tests

open StochasticSimulation.ChemicalReaction.ChemicalReaction
open StochasticSimulation.ChemicalReaction.ChemicalSpecies
open System.Collections.Generic
open NUnit.Framework
open System;

[<TestFixture>] 
type ``Given a Reaction that has non-zero copy number`` ()= class
    let copyNum = 10000
    let system = [ {Species = { Name ="I" } ; Count = copyNum } ; {Species = { Name ="S" } ; Count = copyNum }]

    [<Test>]
    member test.`` find the species it affects``()=
        let reaction =  { Rate = 1000.0 ; Changes = dict[ {Name = "I"}, {Destroyed =1 ; Created=0} ; {Name = "P"}, {Destroyed =0 ; Created=1} ] };
        let affecteds = reaction.Affects
        Assert.AreEqual( List.length affecteds, 2)
        Assert.AreEqual( affecteds.[0].Name, "I")
        Assert.AreEqual( affecteds.[1].Name, "P")


    [<Test>]
    member test.`` find the species it affects when one does not participate in the reaction``()=
        let reaction =  { Rate = 9900.0 ; Changes = dict[ {Name = "I"}, {Destroyed =1 ; Created=0} ; {Name = "S"}, {Destroyed =1 ; Created=1} ] };
        let affecteds = reaction.Affects
        Assert.AreEqual( List.length affecteds, 1)
        Assert.AreEqual( affecteds.[0].Name, "I")


    [<Test>]
    member test.`` find the species it depends on``()=
        let reaction =  { Rate = 1000.0 ; Changes = dict[ {Name = "I"}, {Destroyed =1 ; Created=0} ; {Name = "P"}, {Destroyed =0 ; Created=1} ] };
        let depends = reaction.Depends
        Assert.AreEqual( List.length depends, 1)
        Assert.AreEqual( depends.[0].Name, "I")


    [<Test>]
    member test.`` find the species when it depends on itself``()=
        let reaction =  { Rate = 1000.0 ; Changes = dict[ {Name = "S"}, {Destroyed =1 ; Created=0}] };
        let depends = reaction.Depends
        Assert.AreEqual( List.length depends, 1)
        Assert.AreEqual( depends.[0].Name, "S")

    [<Test>] 
    member test.`` calcualte the propensity correctly for single species being destroyed.`` ()=
        let rate = 0.5
        let reaction = { Rate = rate ; Changes = dict[ {Name = "I"}, {Destroyed =1 ; Created=0}] }
        let propensity = reaction.Propensity system
        Assert.AreEqual(propensity, ( (float)copyNum )*rate)

    [<Test>] 
    member test.`` calcualte the propensity correctly for single species being created.`` ()=
        let rate = 0.5
        let reaction = { Rate = rate ; Changes = dict[ {Name = "I"}, {Destroyed =0 ; Created=1}] }
        let propensity = reaction.Propensity system
        Assert.AreEqual(propensity, rate)

    [<Test>] 
    member test.`` calcualte the propensity correctly in presence of catalyst.`` ()=
        let rate = 0.5
        let reaction = { Rate = rate ; Changes = dict[ {Name = "I"}, {Destroyed =1 ; Created=0} ; {Name = "S"}, {Destroyed =1 ; Created=1} ] }
        let propensity = reaction.Propensity system
        Assert.AreEqual(propensity, rate * 10000.0 * 10000.0)

    [<Test>]
    member test.`` species with same names are equal`` () =
        let s1 = {Name = "A"}
        let s2 = {Name = "A"}

        Assert.AreEqual(s1, s2)


    [<Test>]
    member test.`` species with different names are not equal`` () =
        let s1 = {Name = "A"}
        let s2 = {Name = "B"}

        Assert.AreNotEqual(s1, s2)

    [<Test>]
    member test.`` species changes with same values are equal`` () =
        let c1 = { Destroyed =1 ; Created =0 }
        let c2 = { Destroyed =1 ; Created =0 }

        Assert.AreEqual(c1, c2)

    [<Test>]
    member test.`` recations with different rates are still equal`` () =
        let rate1 = 0.5
        let r1 = { Rate = rate1 ; Changes = dict[ {Name = "I"}, {Destroyed =0 ; Created=1}] }
        let rate2 = 0.6
        let r2 = { Rate = rate2 ; Changes = dict[ {Name = "I"}, {Destroyed =0 ; Created=1}] }
        Assert.AreEqual(r1,r2)

    [<Test>]
    member test.`` recations with different changes are not equal`` () =
        let rate1 = 0.5
        let r1 = { Rate = rate1 ; Changes = dict[ {Name = "I"}, {Destroyed =0 ; Created=1}] }
        let rate2 = 0.6
        let r2 = { Rate = rate2 ; Changes = dict[ {Name = "I"}, {Destroyed =1 ; Created=1}] }
        Assert.AreNotEqual(r1,r2)
end
